/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						 object_registration.h

	$Header: /heroes4/object_registration.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( OBJECT_REGISTRATION_H_INCLUDED )
#define OBJECT_REGISTRATION_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <string>

enum  t_adv_object_type;
class t_qualified_adv_object_type;
class t_stationary_adventure_object;

// -------------------------------------------------------------------
// object creates a stationary adventure object
// -------------------------------------------------------------------
class t_object_factory_base
{
public:
	typedef t_stationary_adventure_object	t_object;
	typedef t_qualified_adv_object_type		t_object_type;

	virtual t_object* create( std::string const& name, t_object_type const& type ) const = 0;
};


// -------------------------------------------------------------------
// object which records function for creating an object
// -------------------------------------------------------------------
class t_object_registration_base
{
public:
	t_object_registration_base( t_adv_object_type type, t_object_factory_base const* factory );
	t_object_registration_base( t_adv_object_type type, int major_subtype,
		                        t_object_factory_base const* factory ); 
	t_object_registration_base( t_adv_object_type type, int major_subtype, int minor_subtype,
		                        t_object_factory_base const* factory ); 
};


// -------------------------------------------------------------------
// templated object factory
// -------------------------------------------------------------------
template <class t_type>
class t_object_factory : public t_object_factory_base
{
public:
	virtual t_object* create( std::string const& name, t_object_type const& type ) const;
};

template <class t_type>
t_stationary_adventure_object* t_object_factory<t_type>::create( std::string const& name,
																 t_object_type const& type ) const
{
	return new t_type( name );
}

// -------------------------------------------------------------------
// templated object registration
// -------------------------------------------------------------------
template <class t_type>
class t_object_registration : public t_object_registration_base
{
public:
	t_object_registration( t_adv_object_type type );
	t_object_registration( t_adv_object_type type, int major_subtype ); 
	t_object_registration( t_adv_object_type type, int major_subtype, int minor_subtype ); 

protected:
	t_object_factory<t_type> m_factory;
};

template <class t_type>
inline t_object_registration<t_type>::t_object_registration( t_adv_object_type type ) 
                                    : t_object_registration_base( type, &m_factory )
{
}

template <class t_type>
inline t_object_registration<t_type>::t_object_registration( t_adv_object_type type, 
														   int major_subtype )
                                    : t_object_registration_base( type, major_subtype,
									                              &m_factory )
{
}

template <class t_type>
inline t_object_registration<t_type>::t_object_registration( t_adv_object_type type, 
														   int               major_subtype, 
														   int               minor_subtype )
                                    : t_object_registration_base( type, major_subtype,
									                              minor_subtype, &m_factory )
{
}

// -------------------------------------------------------------------
// templated object factory
// -------------------------------------------------------------------
template <class t_type>
class t_object_factory_with_type : public t_object_factory_base
{
public:
	virtual t_object* create( std::string const& name, t_object_type const& type ) const;
};

template <class t_type>
t_stationary_adventure_object* t_object_factory_with_type<t_type>::create( std::string const& name,
																 t_object_type const& type ) const
{
	return new t_type( name, type );
}

// -------------------------------------------------------------------
// templated object registration
// -------------------------------------------------------------------
template <class t_type>
class t_register_with_type : public t_object_registration_base
{
public:
	t_register_with_type( t_adv_object_type type );
	t_register_with_type( t_adv_object_type type, int major_subtype ); 
	t_register_with_type( t_adv_object_type type, int major_subtype, int minor_subtype ); 

protected:
	t_object_factory_with_type<t_type> m_factory;
};

template <class t_type>
inline t_register_with_type<t_type>::t_register_with_type( t_adv_object_type type ) 
                                    : t_object_registration_base( type, &m_factory )
{
}

template <class t_type>
inline t_register_with_type<t_type>::t_register_with_type( t_adv_object_type type, 
														   int major_subtype )
                                    : t_object_registration_base( type, major_subtype,
									                              &m_factory )
{
}

template <class t_type>
inline t_register_with_type<t_type>::t_register_with_type( t_adv_object_type type, 
														   int               major_subtype, 
														   int               minor_subtype )
                                    : t_object_registration_base( type, major_subtype,
									                              minor_subtype, &m_factory )
{
}

// -------------------------------------------------------------------
// create a stationary object subtype
// -------------------------------------------------------------------
t_stationary_adventure_object* create_adv_object( std::string const& name );
t_stationary_adventure_object* create_adv_object( std::string const& name,
											      t_qualified_adv_object_type const& type );

#endif // OBJECT_REGISTRATION_H_INCLUDED